﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using CourseDesign_02;

namespace FundamentalsOfCompiling
{
    class ComponentEvent
    {

        
        //static Global global = null;
        //tatic WordParser paser = null;
        static int tabs = 0;
        static Lists lists = new Lists();
        static Facade fascade = new Facade();

        /// <summary>
        /// FileNew_Click
        /// </summary>
        /// <param name="window"></param>
        public static void FileNew_Click(MainWindow window)
        {
            MessageBoxResult mbr = MessageBoxResult.OK;

            if (!rtbIsNull(window.rtbInput) || !rtbIsNull(window.rtbInput))
                mbr = MessageBox.Show("新建文件将会清空 SNL源文件 或 分析结果。\n 是否继续 ？？", "提示", MessageBoxButton.YesNoCancel, MessageBoxImage.Question, MessageBoxResult.Yes);

            switch (mbr)
            {
                case MessageBoxResult.Yes:
                    //  进行参数的初始化
                    window.fileSourcePath = null;

                    //  清空 rtb
                    EditClearInput_Click(window);
                    EditClearOutput_Click(window);
                    break;

                case MessageBoxResult.No:
                    return;

                case MessageBoxResult.Cancel:
                    return;
            }
        }

        /// <summary>
        /// FileOpen_Click
        /// </summary>
        /// <param name="window"></param>
        public static void FileOpen_Click(MainWindow window)
        {
            MessageBoxResult mbr = MessageBoxResult.Yes;
            if (!rtbIsNull(window.rtbInput))
                mbr = MessageBox.Show("SNL 源文件 不为空 \n 打开文件会清空 SNL 源文件\n 是否继续 ??", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.OK);
            if (mbr == MessageBoxResult.Yes)
            {
                window.rtbInput.SelectAll();
                window.rtbInput.Selection.Text = "";
            }
            else
            {
                return;
            }
            string fileSourceContent = null;
            Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
            ofd.DefaultExt = ".txt";
            ofd.Filter = "源文件(*.txt)|*.txt|全部文件(*.*)|*.*";
            if (ofd.ShowDialog() == true)
            {
                window.fileSourcePath = ofd.FileName;

                using (var fileSourceStream = new System.IO.StreamReader(ofd.FileName, Encoding.Default))
                {
                    fileSourceContent = fileSourceStream.ReadToEnd();
                    //window.rtbInput.AppendText(fileSourceContent);
                }   //  using
                fascade.Init(fascade.createSource(sourceType.FILE, window.fileSourcePath));
                //LexicalAnalysis_Click(window);
                //List<TokenType> list = fascade.getTokenList();
                MidiatorOutput mo = new MidiatorOutput(window);
                fascade.printTokenList(mo);

                MidiatorInput mi = new MidiatorInput(window);
                fascade.printTokenList(mi);
                window.rtbInput.AppendText("  \n");

            }   //  ofd.ShowDialog
            
            //GC.Collect();
        }   //  FileOpen_Click

        /// <summary>
        /// FileSaveInput_Click
        /// </summary>
        /// <param name="window"></param>
        public static void FileSaveInput_Click(MainWindow window)
        {
            MessageBoxResult mbr = MessageBoxResult.OK;
            if (rtbIsNull(window.rtbInput))
                mbr = MessageBox.Show("SNL 源文件 为空！！ \n 是否继续保存 ？？", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Question);
            if (mbr == MessageBoxResult.OK)
                rtbSaveContent(window.rtbInput, "SNL源文件", "保存 SNL 源文件");
        }   // FileSaveInput_Click

        /// <summary>
        /// FileSaveOutput_Click
        /// </summary>
        /// <param name="window"></param>
        public static void FileSaveOutput_Click(MainWindow window)
        {
            MessageBoxResult mbr = MessageBoxResult.OK;
            if (rtbIsNull(window.rtbOutput))
                mbr = MessageBox.Show("SNL 源文件 为空！！ \n 是否继续保存 ？？", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Question);
            if (mbr == MessageBoxResult.OK)
                rtbSaveContent(window.rtbOutput, "分析结果", "保存 分析结果");
        }   //  FileSaveOutput_Click

        /// <summary>
        /// FileQuit_Click
        /// </summary>
        /// <param name="window"></param>
        public static void FileQuit_Click(MainWindow window)
        {
            MessageBoxResult mbr = MessageBoxResult.Yes;
            if (!rtbIsNull(window.rtbInput) || !rtbIsNull(window.rtbOutput))
                mbr = MessageBox.Show("请确认在推出前保存 \nSNL源文件 和 分析结果 \n请确认是否退出？？", "提示", MessageBoxButton.YesNo, MessageBoxImage.Question);
            if (mbr == MessageBoxResult.Yes)
                window.Close();
            else
                return;
        }   //  FileQuit_Click

        /// <summary>
        /// EditRevoke_Click
        /// </summary>
        /// <param name="window"></param>
        public static void EditRevoke_Click(MainWindow window)
        {
            window.rtbInput.Undo();
        }

        /// <summary>
        /// EditRedo_Click
        /// </summary>
        /// <param name="window"></param>
        public static void EditRedo_Click(MainWindow window)
        {
            window.rtbInput.Redo();
        }

        /// <summary>
        /// EditNote_Click
        /// </summary>
        /// <param name="window"></param>
        public static void EditNote_Click(MainWindow window)
        {
            string note = window.rtbInput.Selection.Text;
            window.rtbInput.Selection.Text = "";
            //window.rtbInput.Selection.Select(window.rtbInput.CaretPosition, window.rtbInput.Document.ContentEnd);
            if (note == "")
                return;
            window.rtbInput.Selection.Select(window.rtbInput.CaretPosition, window.rtbInput.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward));
            window.rtbInput.Cut();

            window.rtbInput.AppendText("\n{  ");
            window.rtbInput.CaretPosition = window.rtbInput.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
            window.rtbInput.AppendText(note);
            window.rtbInput.CaretPosition = window.rtbInput.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
            window.rtbInput.AppendText("  }\n");
            window.rtbInput.Paste();
        }

        /// <summary>
        /// EditUnNote_Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static void EditUnNote_Click(MainWindow  window)
        {
            string str = window.rtbInput.Selection.Text;
            string ss = "";
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] != '{' && str[i] != '}')
                ss += str[i];
            }
            window.rtbInput.Selection.Text = ss;

            window.rtbInput.Selection.Select(window.rtbInput.Document.ContentStart, window.rtbInput.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward));
            string sour = window.rtbInput.Selection.Text;
            window.rtbInput.Selection.Text = "";

            fascade.Init(fascade.createSource(sourceType.FILE, window.fileSourcePath));
            MidiatorInput mi = new MidiatorInput(window);
            fascade.printTokenList(mi);
            window.rtbInput.AppendText("  \n");

            window.rtbInput.ScrollToEnd();
        }
        /// <summary>
        /// EditClearInput_Click
        /// </summary>
        /// <param name="window"></param>
        public static void EditClearInput_Click(MainWindow window)
        {
            window.rtbInput.Selection.Select(window.rtbInput.Document.ContentStart, window.rtbInput.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward));
            window.rtbInput.Selection.Text = "";
        }

        /// <summary>
        /// EditClearOutput_Click
        /// </summary>
        /// <param name="window"></param>
        public static void EditClearOutput_Click(MainWindow window)
        {
            window.rtbOutput.Selection.Select(window.rtbOutput.Document.ContentStart, window.rtbOutput.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward));
            window.rtbOutput.Selection.Text = "";
        }

        /// <summary>
        /// HelpHelp_Click
        /// </summary>
        /// <param name="window"></param>

        public static void HelpHelp_Click(MainWindow window)
        {
            //System.Diagnostics.Process.Start("F:\\MV\\小小 - 容祖儿.flv");
            System.Diagnostics.Process.Start("..\\..\\File\\help.chm");
            //System.Diagnostics.Process.Start("D:\\Users\\LENOVO\\Desktop\\help.chm");
        }

        /// <summary>
        /// HelpAboutus_Click
        /// </summary>
        /// <param name="window"></param>
        public static void HelpAboutus_Click(MainWindow window)
        {
            System.Diagnostics.Process.Start("..\\..\\File\\help.chm");
            //System.Diagnostics.Process.Start("D:\\Users\\LENOVO\\Desktop\\help.chm");
        }

        /// <summary>
        /// rtbInput_KeyUp
        /// </summary>
        /// <param name="window"></param>
        /// <param name="kea"></param>
        public static void rtbInput_KeyUp(MainWindow window, KeyEventArgs kea)
        {
            TextRange tr;
            if (kea.Key == Key.Back)
            {
                tr = new TextRange(window.rtbInput.Document.ContentStart, window.rtbInput.Document.ContentEnd);
                if (tr.Text == window.rtbInput.Selection.Text)
                {
                    window.rtbInput.Selection.Text = "";
                    return;
                }
            }
            if (kea.Key == Key.OemCopy)
            {
                MessageBox.Show("Copy");
                return;
            }

            if (kea.Key == Key.Enter || kea.Key == Key.Space || kea.Key == Key.Tab)
            {
                tr = getCurrentTextRanger(window.rtbInput, window.rtbInput.CaretPosition.GetNextInsertionPosition(LogicalDirection.Backward));
                if (tr != null)
                    colorTextRange(tr);
            }

            tr = getCurrentTextRanger(window.rtbInput, window.rtbInput.CaretPosition);
            if (tr != null)
                colorTextRange(tr);
        }

        /// <summary>
        /// rtbOutput_MouseDoubleClick
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static void rtbOutput_MouseDoubleClick(MainWindow window)
        {
            
            TextPointer tp = window.rtbOutput.CaretPosition;
            TextPointer tpStart = tp.GetLineStartPosition(0);
            TextPointer tpEnd = tp.GetLineStartPosition(1);
            TextRange tr = new TextRange(tpStart, tpEnd);
            string str = tr.Text;
            int line = 0;
            int i = 0;
            for (i = 0; i <= str.Length; i++)
                if (str[i] == ':')
                    break;
            i++;
            i++;
            while(str[i] >= '0' && str[i] <= '9')
            {
                line = line * 10 + (int)(str[i] - '0');
                i++;
            }

            if (line == 0) return; 
            tp = window.rtbInput.Document.ContentStart;
            int lines = line - 1;
            tpStart = tp.GetLineStartPosition(lines);
            tpEnd = tp.GetLineStartPosition(line);
            tr = new TextRange(tpStart, tpEnd);
            tr.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.LightBlue));
            /*
            int left = tp.GetTextRunLength(LogicalDirection.Forward);
            int right = tp.GetTextRunLength(LogicalDirection.Backward);
            tpStart = tp.GetPositionAtOffset(0 - left);
            tpEnd = tp.GetPositionAtOffset(right);
            TextRange tr = new TextRange(tpStart, tpEnd);
            tr.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.LightBlue));
             */
            /*
            while (getNextChar(window.rtbOutput, tpStart.GetNextInsertionPosition(LogicalDirection.Backward)) != '\t')
                tpStart = tpStart.GetNextInsertionPosition(LogicalDirection.Backward);
            //while(tpStart.GetNextInsertionPosition(LogicalDirection.Backward) != null)
            //    tpStart = tpStart.GetNextInsertionPosition(LogicalDirection.Backward);
            while (getNextChar(window.rtbOutput, tpEnd) != '\t')
                tpStart = tpStart.GetNextInsertionPosition(LogicalDirection.Forward);
            //while(tpEnd.GetNextInsertionPosition(LogicalDirection.Forward) != null)
            //    tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
            window.rtbOutput.Selection.Select(tpStart, tpEnd);
             */
        }
        /// <summary>
        /// LexicalAnalysis_Click
        /// </summary>
        /// <param name="window"></param>
        public static void LexicalAnalysis_Click(MainWindow window)
        {
            /*
            List<TokenType> list = fascade.getTokenList();
            MidiatorOutput mo = new MidiatorOutput(window);
            fascade.printTokenList(mo);
             */
            TextRange tr = new TextRange(window.rtbInput.Document.ContentStart, window.rtbInput.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward));
            fascade.Init(fascade.createSource(sourceType.STRING, tr.Text+"\n"));
            //LexicalAnalysis_Click(window);
            //List<TokenType> list = fascade.getTokenList();
            MidiatorOutput mo = new MidiatorOutput(window);
            fascade.printTokenList(mo);

            //MidiatorInput mi = new MidiatorInput(window);
            //fascade.printTokenList(mi);
            //window.rtbInput.AppendText("  \n");
        }

        /// <summary>
        /// SyntaxAnalysis_Click
        /// </summary>
        /// <param name="window"></param>
        public static void SyntaxAnalysis_Click(MainWindow window)
        {
           // try
           // {
                fascade.SyntaxParse();
                MidiatorOutput mos = new MidiatorOutput(window);
                fascade.printTree(mos);
           // }
           // catch (Exception e)
           // {
           //     MessageBox.Show(e.Message);
            //}
        }




        /* ***************************************************************
         * **   本类需要用到的一些函数
         * ************************************************************ */
        /*
        /// <summary>
        /// 打印 TokenList 到 rtbInput
        /// </summary>
        /// <param name="window"></param>
        /// <param name="list"></param>
        public static void printTokenListInput(MainWindow window, List<TokenType> list)
        {
            //List<TokenType> ltt = paser.getList();
            if (list == null) return;
            if (list.Count == 0) return;
            foreach (TokenType tt in list)
            {
                printTokenInput(window, tt);
            }
        }
       
        protected static void printTokenInput(MainWindow window, TokenType token)
        {
            switch (token.Lex)
            {
                case LexType.PROGRAM:
                case LexType.PROCEDURE:
                case LexType.TYPE:
                case LexType.VAR:
                case LexType.IF:
                case LexType.THEN:
                case LexType.ELSE:
                case LexType.FI:
                case LexType.WHILE:
                case LexType.DO:
                case LexType.ENDWH:
                case LexType.BEGIN:
                case LexType.END:
                case LexType.READ:
                case LexType.WRITE:
                case LexType.ARRAY:
                case LexType.OF:
                case LexType.RECORD:
                case LexType.RETURN:
                case LexType.INTEGER:
                case LexType.CHAR1:
                    Write(window, token.Sem, Colors.Red);
                    break;
                case LexType.ASSIGN:
                case LexType.LT:
                case LexType.EQ:
                case LexType.PLUS:
                case LexType.MINUS:
                case LexType.TIMES:
                case LexType.OVER:
                case LexType.LPAREN:
                case LexType.RPAREN:
                case LexType.LMIDPAREN:
                case LexType.RMIDPAREN:
                    Write(window, token.Sem, Colors.Green);
                    break;

                case LexType.SEMI:// window.WriteLine(";"); break;
                case LexType.COLON:// window.WriteLine(":"); break;
                case LexType.COMMA:// window.WriteLine(","); break;
                case LexType.DOT:// window.WriteLine("."); break;
                case LexType.UNDERANGE:// window.WriteLine(".."); break;
                case LexType.ENDFILE1:// window.WriteLine("EOF"); break;
                case LexType.INTC:// window.WriteLine("INTC, val= " + token.Sem); break;
                case LexType.CHARC:// window.WriteLine("CHARC, letter= " + token.Sem); break;
                case LexType.ID: //window.WriteLine("ID, name= " + token.Sem); break;
                case LexType.ERROR1://window.WriteLine("ERROR: " + token.Sem); break;
                    Write(window, token.Sem, Colors.Black);
                    break;
                case LexType.CRT://window.WriteLine("记录的是换行符号"); break;
                    Write(window, "\n", Colors.Black);
                    break;
                default://window.WriteLine("Unknown token:" + token.Lex); break;
                    Write(window, token.Sem, Colors.Black);
                    break;
            }
        }

        public static void Write(MainWindow window, string str, Color color)
        {
            if (lists.leftTab.Contains(str) && (tabs > 0)) tabs--;
            if (lists.rightTab.Contains(str)) tabs++;
            window.rtbInput.AppendText(" " + str);
            if (str == "\n")
            {
                for (int i = 0; i < tabs; i++) window.rtbInput.AppendText("\t");
            }


            TextPointer tpEnd = window.rtbInput.Document.ContentEnd;
            TextPointer tpStart = tpEnd.GetNextInsertionPosition(LogicalDirection.Backward);
            for (int i = 0; i < str.Length; i++) tpStart = tpStart.GetNextInsertionPosition(LogicalDirection.Backward);
            TextRange tr = new TextRange(tpStart, tpEnd);
            tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(color));
            bool right = lists.rightTab.Contains(str);
        }
         */

        /*
        /// <summary>
        /// 将TokenList输出到分析结果
        /// </summary>
        /// <param name="window"></param>
        public static void printTokenlistOutput(MainWindow window, List<TokenType> list)
        {
            window.WriteLine("输出TokenList（即是list）中信息");
            int num;
            TokenType currentToken;
            
            //if (global.operateError)
            //    window.WriteLine("----词法分析有错，以ERROR打头的为错误的Token：\n");
            
            //else window.WriteLine("----词法分析无错：Token序列如下：\n");
            int count = list.Count;
            if (count <= 0)
            {
                window.WriteLine("Token序列为空");
                return;
            }
            for (num = 0; num < count; num++)
            {
                currentToken = list[num];
                window.Write("行号: " + currentToken.lineshow);
                printTokenOutput(window, currentToken);
            }
        }

        protected static void printTokenOutput(MainWindow window, TokenType token)
        {
            switch (token.Lex)
            {
                case LexType.PROGRAM:
                case LexType.PROCEDURE:
                case LexType.TYPE:
                case LexType.VAR:
                case LexType.IF:
                case LexType.THEN:
                case LexType.ELSE:
                case LexType.FI:
                case LexType.WHILE:
                case LexType.DO:
                case LexType.ENDWH:
                case LexType.BEGIN:
                case LexType.END:
                case LexType.READ:
                case LexType.WRITE:
                case LexType.ARRAY:
                case LexType.OF:
                case LexType.RECORD:
                case LexType.RETURN:
                case LexType.INTEGER:
                case LexType.CHAR1:
                    window.WriteLine("reserved word: " + token.Sem);
                    break;
                case LexType.ASSIGN: window.WriteLine(":="); break;

                case LexType.LT: window.WriteLine("<"); break;

                case LexType.EQ: window.WriteLine("="); break;

                case LexType.PLUS: window.WriteLine("+"); break;

                case LexType.MINUS: window.WriteLine("-"); break;

                case LexType.TIMES: window.WriteLine("*"); break;

                case LexType.OVER: window.WriteLine("/"); break;

                case LexType.LPAREN: window.WriteLine("("); break;

                case LexType.RPAREN: window.WriteLine(")"); break;

                case LexType.LMIDPAREN: window.WriteLine("["); break;

                case LexType.RMIDPAREN: window.WriteLine("]"); break;

                case LexType.SEMI: window.WriteLine(";"); break;

                case LexType.COLON: window.WriteLine(":"); break;

                case LexType.COMMA: window.WriteLine(","); break;

                case LexType.DOT: window.WriteLine("."); break;

                case LexType.UNDERANGE: window.WriteLine(".."); break;

                case LexType.ENDFILE1: window.WriteLine("EOF"); break;

                case LexType.INTC:
                    window.WriteLine("INTC, val= " + token.Sem);
                    break;

                case LexType.CHARC:
                    window.WriteLine("CHARC, letter= " + token.Sem);
                    break;

                case LexType.ID:
                    window.WriteLine("ID, name= " + token.Sem);
                    break;

                case LexType.ERROR1:
                    window.WriteLine("ERROR: " + token.Sem);
                    break;
                case LexType.CRT:
                    window.WriteLine("记录的是换行符号");
                    break;
                default:
                    window.WriteLine("Unknown token:" + token.Lex);
                    break;
            }
        }
        */

        //  判断 RichTextBox 内容是否为空
        public static bool rtbIsNull(RichTextBox rtb)
        {
            TextRange tr = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward));
            if (tr.Text == "") return true;
            else return false;
        }

        //  保存 RichTextBox 内容，到文件
        private static void rtbSaveContent(RichTextBox rtb, string name = "文本文件", string title = "保存文件")
        {
            //  如果 输入框 为空，则提示
            if (rtbIsNull(rtb)) return;

            Microsoft.Win32.SaveFileDialog dialogSaveFile = new Microsoft.Win32.SaveFileDialog();
            dialogSaveFile.DefaultExt = "txt";//默认扩展名
            dialogSaveFile.AddExtension = true;//是否自动添加扩展名
            dialogSaveFile.Filter = "文本文件(*.txt)|.txt|自定义文件(*.*)|*.*";
            dialogSaveFile.OverwritePrompt = true;//文件已存在是否提示覆盖
            dialogSaveFile.FileName = name;//默认文件名
            dialogSaveFile.CheckPathExists = true;//提示输入的文件名无效
            dialogSaveFile.Title = title;

            //显示对话框
            bool? b = dialogSaveFile.ShowDialog();
            if (b == true)//点击保存
            {
                string fileOutput = dialogSaveFile.FileName;
                TextRange textRange = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
                string outputContent = textRange.Text;
                try
                {
                    Stream stream = File.OpenWrite(fileOutput);
                    using (StreamWriter writer = new StreamWriter(stream))
                    {
                        writer.Write(outputContent);
                        writer.Close();
                    }
                    stream.Close();
                }
                catch (IOException ex)
                {
                    //window.outPut(ex.Message);
                    MessageBox.Show(ex.Message, "Exception", MessageBoxButton.OK, MessageBoxImage.Warning);
                }   // cathc
            }   // if
        }   //  rtbSaveContent

        //  得到当前 TextPointer 的所在字符串的 TextRanger
        private static TextRange getCurrentTextRanger(RichTextBox rtb, TextPointer tp)
        {
            //TextPointer tp = rtb.CaretPosition;
            if (tp == null)
                return null;
            TextPointer tpStart = tp;
            TextPointer tpEnd;
            TextRange tr;
            char ch;
            int type = 0;

            //  string
            ch = getNextChar(rtb, tpStart.GetNextInsertionPosition(LogicalDirection.Backward));

            while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_'))
            {
                tpStart = tpStart.GetNextInsertionPosition(LogicalDirection.Backward);
                ch = getNextChar(rtb, tpStart.GetNextInsertionPosition(LogicalDirection.Backward));
                type = 1;
            }

            if (type == 0)
            {
                while ((ch == '(') || (ch == ')') || (ch == '[') || (ch == ']'))
                {
                    tpStart = tpStart.GetNextInsertionPosition(LogicalDirection.Backward);
                    ch = getNextChar(rtb, tpStart.GetNextInsertionPosition(LogicalDirection.Backward));
                    type = 2;
                }
            }

            if (type == 0)
            {
                while ((ch == '+') || (ch == '-') || (ch == '*') || (ch == '/') || (ch == '%') || (ch == '='))
                {
                    type = 3;
                    tpStart = tpStart.GetNextInsertionPosition(LogicalDirection.Backward);
                    ch = getNextChar(rtb, tpStart.GetNextInsertionPosition(LogicalDirection.Backward));
                }

            }

            tr = new TextRange(tp, rtb.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward));
            if (tr.IsEmpty)
                tpEnd = rtb.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
            else
            {
                tpEnd = tp;
                ch = getNextChar(rtb, tpEnd);
                switch (type)
                {
                    case 0:
                        while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_'))
                        {
                            tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                            ch = getNextChar(rtb, tpEnd);
                            type = 1;
                        }
                        if (type == 1) break;
                        while ((ch == '(') || (ch == ')') || (ch == '[') || (ch == ']'))
                        {
                            tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                            ch = getNextChar(rtb, tpEnd);
                            type = 2;
                        }
                        if (type != 0) break;
                        while ((ch == '+') || (ch == '-') || (ch == '*') || (ch == '/') || (ch == '%') || (ch == '='))
                        {
                            tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                            ch = getNextChar(rtb, tpEnd);
                            type = 3;
                        }
                        if (type != 0) break;

                        break;

                    case 1:
                        while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_'))
                        {
                            tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                            ch = getNextChar(rtb, tpEnd);
                        }
                        break;

                    case 2:
                        while ((ch == '(') || (ch == ')') || (ch == '[') || (ch == ']'))
                        {
                            tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                            ch = getNextChar(rtb, tpEnd);
                        }
                        break;

                    case 3:
                        while ((ch == '+') || (ch == '-') || (ch == '*') || (ch == '/') || (ch == '%') || (ch == '='))
                        {
                            tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                            ch = getNextChar(rtb, tpEnd);
                        }
                        break;

                    default:
                        break;
                }

                /*
                while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_'))
                {
                    tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                    ch = getNextChar(rtb, tpEnd);
                }
                while ((ch == '(') || (ch == ')') || (ch == '[') || (ch == ']'))
                {
                    tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                    ch = getNextChar(rtb, tpEnd);
                }
                while ((ch == '+') || (ch == '-') || (ch == '*') || (ch == '/') || (ch == '%') || (ch == '='))
                {
                    tpEnd = tpEnd.GetNextInsertionPosition(LogicalDirection.Forward);
                    ch = getNextChar(rtb, tpEnd);
                }
                 */
            }

            tr = new TextRange(tpStart, tpEnd);
            if (type == 0 && tpStart.GetNextInsertionPosition(LogicalDirection.Backward) != null)
                tr = new TextRange(tpStart.GetNextInsertionPosition(LogicalDirection.Backward), tpEnd);
            return tr;
        }   //  getCurrentTextRanger

        //  去的当前 TextPoint 的下一个字符
        private static char getNextChar(RichTextBox rtb, TextPointer tp)
        {
            if (tp == null) return ' ';
            TextPointer tpNext = tp.GetNextInsertionPosition(LogicalDirection.Forward);
            if (tpNext == null) return ' ';
            TextRange tr = new TextRange(tp, tpNext);
            String str = tr.Text;
            return str[0];
        }   //  getNextChar

        //  给字符串添加相应的颜色
        private static void colorTextRange(TextRange tr)
        {
            List<string> listCalcultor = new List<string>();
            listCalcultor.Add("+");
            listCalcultor.Add("-");
            listCalcultor.Add("*");
            listCalcultor.Add("/");
            listCalcultor.Add("%");
            listCalcultor.Add("+=");
            listCalcultor.Add("-=");
            listCalcultor.Add("*=");
            listCalcultor.Add("/=");
            listCalcultor.Add("%=");
            listCalcultor.Add("++");
            listCalcultor.Add("--");
            listCalcultor.Add("=");
            listCalcultor.Add("==");
            listCalcultor.Add("!=");


            if (lists.reservedWord.Contains(tr.Text))
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Red));
            else if (listCalcultor.Contains(tr.Text))
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Green));
            else
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Black));
        }

    }
}   //  namespace: FundamentalsOfCompiling
